/****************************************************************************
 *  QLyrics - A simple lyrics viewer.                                       *
 *  Copyright (C) 2008  hsys <hanshuiys@gmail.com>                          *
 *                                                                          *
 *  This program is free software; you can redistribute it and/or modify    *
 *  it under the terms of the GNU General Public License as published by    *
 *  the Free Software Foundation; either version 3 of the License, or       *
 *  (at your option) any later version.                                     *
 *                                                                          *
 *  This program is distributed in the hope that it will be useful,         *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 *  GNU General Public License for more details.                            *
 *                                                                          *
 *  You should have received a copy of the GNU General Public License       *
 *  along with this program; if not, write to the Free Software Foundation, *
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA       *
 ****************************************************************************/

#include "lyricsmanager.h"
#include "lyricslocalprovider.h"
#include "lyricsttprovider.h"
#include "lyricsbaiduprovider.h"
#include "player.h"

LyricsManager* LyricsManager::sm_inst = NULL;

LyricsManager::LyricsManager(QObject* parent) : QObject(parent) {
    m_currentJob = NULL;
    m_status = LyricsProvider::NotFound;

    // add local lyrics search
    m_lyricsProvider.push_back(new LyricsLocalProvider::Builder());
    m_lyricsProvider.push_back(new LyricsTTProvider::Builder());
    m_lyricsProvider.push_back(new LyricsBaiduProvider::Builder());

    // connect signals
    Player* player = Player::getInstance();
    connect(player, SIGNAL(trackChanged()), SLOT(slotTrackChanged()));
};

LyricsManager::~LyricsManager() {
    // delete all builder
    std::vector<LyricsProvider::Builder*>::iterator px;
    for (px = m_lyricsProvider.begin(); px != m_lyricsProvider.end(); ++px) {
        delete *px;
    };
};

void LyricsManager::buildInstance(QObject* parent) {
    if (sm_inst == NULL)
        sm_inst = new LyricsManager(parent);
};

LyricsManager* LyricsManager::getInstance() {
    return sm_inst;
};

void LyricsManager::searchAll(const Track& track) {
    // create the job instance
    m_currentJob = new LyricsJob(track, this);
    connect(m_currentJob, SIGNAL(signalMultiChoice(LyricsJob*)), SLOT(slotMultiChoice(LyricsJob*)));
    connect(m_currentJob, SIGNAL(signalJobDone(LyricsJob*)), SLOT(slotJobDone(LyricsJob*)));
    // add all providers to the job
    std::vector<LyricsProvider::Builder*>::const_iterator ix;
    for (ix = m_lyricsProvider.begin(); ix != m_lyricsProvider.end(); ++ix) {
        m_currentJob->addProvider(*ix);
    };
    // start the job
    m_currentJob->start();
};

void LyricsManager::search(const Track& track, const int providerId) {
    if (providerId < m_lyricsProvider.size() && providerId >= 0) {
        // create the job instance
        m_currentJob = new LyricsJob(track, this);
        connect(m_currentJob, SIGNAL(signalMultiChoice(LyricsJob*)), SLOT(slotMultiChoice(LyricsJob*)));
        connect(m_currentJob, SIGNAL(signalJobDone(LyricsJob*)), SLOT(slotJobDone(LyricsJob*)));
        m_currentJob->addProvider(m_lyricsProvider[providerId]);
        m_currentJob->setIsPrompt(true);
        m_currentJob->start();
    };
};

void LyricsManager::reloadLyrics() {
    Player* player = Player::getInstance();
    if (player->getStatus() != Player::Idle)
        slotTrackChanged();
    /*if (!m_filename.isEmpty() && m_status == LyricsProvider::Success) {
        emit signalLyricsChanged(NULL, LyricsProvider::Searching);
        m_lyrics.loadFromFile(m_filename);
        emit signalLyricsChanged(&m_lyrics, m_status);
    };*/
};

void LyricsManager::slotTrackChanged() {
    Player* player = Player::getInstance();
    m_lyrics.clear();
    emit signalStatusChanged(LyricsProvider::Searching);
    searchAll(player->getTrack());
};

void LyricsManager::slotMultiChoice(LyricsJob* job) {
    // if the function is not emitted by current job, just ignore
    if (m_currentJob != job) {
        job->deleteLater();
    } else {
        emit signalMultiChoice(job);
    };
};

void LyricsManager::slotJobDone(LyricsJob* job) {
    // if the function is not emitted by current job, just ignore
    if (m_currentJob == job) {
        // read job result
        m_filename = job->getFilename();
        m_status = job->getStatus();
        if (m_status == LyricsProvider::Success) {
            m_lyrics.loadFromFile(m_filename);
        } else {
            m_filename = "";
            m_lyrics.clear();
        };
        emit signalStatusChanged(m_status);
    };
    job->deleteLater();
};
